﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.CodeModel;
using PostSharp.CodeWeaver;
using PostSharp.Collections;

namespace MicroContainer.CompileTime
{
   internal class RewriteCreateContainerAdvice : IAdvice
   {
      private TypeDefDeclaration _containerType;
      private bool _staticContainer;

      public RewriteCreateContainerAdvice(TypeDefDeclaration containerType, bool staticContainer)
      {
         _containerType = containerType;
         _staticContainer = staticContainer;
      }

      #region IAdvice Members
      public int Priority
      {
         get { return 0; }
      }
      public bool RequiresWeave(WeavingContext context)
      {
         return true;
      }
      public void Weave(WeavingContext context, InstructionBlock block)
      {         
         IEnumerator<InstructionSequence> enu = block.MethodBody.GetInstructionSequenceEnumerator();
         while (enu.MoveNext())
         {
            enu.Current.Remove();
         }
         InstructionSequence instructionSequence = block.MethodBody.CreateInstructionSequence();
         block.AddInstructionSequence(instructionSequence, NodePosition.After, null);
         context.InstructionWriter.AttachInstructionSequence(instructionSequence);
         if (_staticContainer)
         {
            FieldDefDeclaration soleInstance = _containerType.Fields.GetByName("_soleInstance");
            context.InstructionWriter.EmitInstructionField(OpCodeNumber.Ldsfld, soleInstance);
         }
         else
         {
            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj,
                                                            _containerType.Methods.GetOneByName(".ctor").Translate(
                                                               block.Module));
         }
         context.InstructionWriter.EmitInstruction(OpCodeNumber.Ret);
         context.InstructionWriter.DetachInstructionSequence();         
      }
      #endregion
   }
}
